package com.example.chcrm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.chcrm.entity.common.*;
import com.example.chcrm.entity.employee.EmployeeVo;
import com.example.chcrm.entity.employee.SupplierPort;
import com.example.chcrm.entity.supplier.HighwaySupplierCar;
import com.example.chcrm.entity.supplier.WaterwaySupplierShip;
import com.example.chcrm.entity.vehicle.*;
import com.example.chcrm.mapper.*;
import com.example.chcrm.service.ShipDeployInfoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

/**
 * @Author 邹
 * @Date 2025/4/27 5:06
 * @Version 1.0
 */
@Service
public class ShipDeployInfoServiceImpl <T> implements ShipDeployInfoService<T> {
    @Autowired
    private ShipDeployInfoMapper shipDeployInfoMapper;
    @Autowired
    private WaterwaySupplierShipMapper waterSupplierShipMapper;
    @Autowired
    private OperateRecordMapper operateRecordMapper;
    @Autowired
    private SupplierPortMapper supplierPortMapper;
    @Autowired
    private TransportChildCvMapper transportChildMapper;
    @Autowired
    private VehicleDeployCarCvMapper carCvMapper;
    @Autowired
    private TransportPlanCvMapper planCvMapper;
    @Override
    public ResponseMsg<IPage<ShipDeployInfo>> pageList(ShipDeployInfo queryParam) {
        QueryWrapper<ShipDeployInfo> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(queryParam.getSupplierName())) {
            queryWrapper.like("supplier_name", queryParam.getSupplierName());
        }

        // 船舶名称模糊匹配
        if (StringUtils.isNotBlank(queryParam.getShipName())) {
            queryWrapper.like("ship_name", queryParam.getShipName());
        }

        // 航次号模糊匹配
        if (StringUtils.isNotBlank(queryParam.getVoyageNumber())) {
            queryWrapper.like("voyage_number", queryParam.getVoyageNumber());
        }

        //---------- 港口查询条件 ----------
        // 起始港名称模糊查询
        if (StringUtils.isNotBlank(queryParam.getStartPortName())) {
            queryWrapper.like("start_port_name", queryParam.getStartPortName());
        }

        // 到达港（交车港）名称模糊查询
        if (StringUtils.isNotBlank(queryParam.getDeliveryPortName())) {
            queryWrapper.like("delivery_port_name", queryParam.getDeliveryPortName());
        }

        //---------- 状态精确查询 ----------
        if (queryParam.getStatus() != null) {
            queryWrapper.eq("status", queryParam.getStatus());
        }

        // 默认排序（按创建时间倒序）
        queryWrapper.eq("is_deleted",0);
        queryWrapper.orderByDesc("create_time");
        List<ShipDeployInfo> list = shipDeployInfoMapper.selectList(queryWrapper);
        ResponseMsg<IPage<ShipDeployInfo>> iPageResponseMsg = new ResponseMsg<>();
        Page<ShipDeployInfo> page = new Page<>();
        page.setRecords(list);
        page.setTotal(list.size());
        page.setSize(queryParam.getRows());
        page.setCurrent(queryParam.getPage());
        iPageResponseMsg.setData(page);
        iPageResponseMsg.success("查询成功");
        return iPageResponseMsg;
    }

    @Override
    public ResponseMsg<Object> add(ShipDeployInfo shipDeploy, EmployeeVo empVo) {
        ResponseMsg<Object> msg = new ResponseMsg<Object>();
        //-------------验证船舶信息-------------
        WaterwaySupplierShip supplierShip = waterSupplierShipMapper.selectOne(
               new QueryWrapper<WaterwaySupplierShip>().eq("name",shipDeploy.getShipName()).eq("is_enable",1));
        if (supplierShip == null || supplierShip.getIsDeleted() != BasicDoc.NOT_DELETE) {
            msg.fail("添加失败，船舶不存在");
            return msg;
        }
        if (supplierShip.getDeployStatus() != 0) {
            msg.fail("添加失败，船舶存在调配任务");
            return msg;
        }
        if (!StringUtils.isNotBlank(shipDeploy.getVoyageNumber())){
            msg.fail("添加失败，航次号不能为空");
            return msg;
        }
        ShipDeployInfo sp = shipDeployInfoMapper.selectOne(new QueryWrapper<ShipDeployInfo>()
                .eq("voyage_number",shipDeploy.getVoyageNumber()).eq("ship_name",shipDeploy.getShipName())
                .eq("is_deleted",0));
        if(sp !=null){
            msg.fail("添加失败，船舶航次号已存在");
            return msg;
        }
        shipDeploy.setVoyageNumber(shipDeploy.getVoyageNumber());    //航次编号
        shipDeploy.setCaptainTel(shipDeploy.getCaptainTel());   //船长电话
        String uuid = RandomHelper.uuid();  //船舶调度任务主id
        //组装船舶任务调配数据
        shipDeploy.setId(uuid);
        shipDeploy.setSupplierId(supplierShip.getSupplierId());        //供应商id
        shipDeploy.setSupplierName(supplierShip.getSupplierName());    //供应商名称
        shipDeploy.setShipId(supplierShip.getId());        //船舶id
        shipDeploy.setShipName(supplierShip.getName());    //船舶名称
        if (shipDeploy.getLoadingNum()!=null) {
            shipDeploy.setLoadingNum(shipDeploy.getLoadingNum());  //预计装车数量
        }else {
            msg.fail("操作失败，请填写预计装船数量");
            return msg;
        }
        shipDeploy.setLeftoverNum(0);          //实际装车数量
        shipDeploy.setStatus(0);
        shipDeploy.setIsDeleted(BasicDoc.NOT_DELETE);
        SupplierPort startPort = supplierPortMapper.selectOne(new QueryWrapper<SupplierPort>()
                .eq("port_name",shipDeploy.getStartPortName()).eq("is_deleted",0)
                .eq("status",1));
        //-----------验证到达港口-----------
        SupplierPort endPort = supplierPortMapper.selectOne(new QueryWrapper<SupplierPort>()
                .eq("port_name",shipDeploy.getDeliveryPortName()).eq("is_deleted",0)
                .eq("status",1));
        if (startPort == null || startPort.getIsDeleted() != BasicDoc.NOT_DELETE) {
            msg.fail("操作失败，起始港口不存在");
            return msg;
        }
        //-----------验证到达港口-----------
        if (endPort == null || endPort.getIsDeleted() != BasicDoc.NOT_DELETE) {
            msg.fail("操作失败，到达港口不存在");
            return msg;
        }
        //起始港口
        shipDeploy.setStartPortId(startPort.getId());
        shipDeploy.setStartId(startPort.getAreaId());
        shipDeploy.setStartFullId(startPort.getAreaFullId());
        shipDeploy.setStartName(startPort.getArea());
        shipDeploy.setStartCoordinate(startPort.getCoordinate());
        shipDeploy.setStartPortName(startPort.getPortName());
        //到达港口
        shipDeploy.setDeliveryPortId(endPort.getId());
        shipDeploy.setDeliveryId(endPort.getAreaId());
        shipDeploy.setDeliveryFullId(endPort.getAreaFullId());
        shipDeploy.setDeliveryName(endPort.getArea());
        shipDeploy.setDeliveryCoordinate(endPort.getCoordinate());
        shipDeploy.setDeliveryPortName(endPort.getPortName());

        shipDeploy.setCreateTime(new Date());
        shipDeployInfoMapper.insert(shipDeploy);
        //修改船舶状态
        supplierShip.setStatus(1);
//        supplierShip.setDeployStatus(1);
        waterSupplierShipMapper.updateById(supplierShip);
        //添加操作日志
        OperateRecord ope = new OperateRecord();
        ope.setId(RandomHelper.uuid());
        ope.setOperateType(OperateRecord.OPE_ADD);
        ope.setSourceId(uuid);
        if (empVo !=null){
            ope.setOperationName(empVo.getEmpNm());
            ope.setOperationId(empVo.getId());
        }
        operateRecordMapper.insert(ope);
        msg.success("添加成功");
        return msg;
    }

    @Override
    public ResponseMsg<Object> startLoading(ShipDeployInfo operationDdeploy, EmployeeVo empVo) {
        ResponseMsg<Object> msg = new ResponseMsg<Object>();
        //--------------查询司机调配信息--------------
        ShipDeployInfo oldDeployDriver = shipDeployInfoMapper.selectById(operationDdeploy.getId());
        if (oldDeployDriver == null || oldDeployDriver.getIsDeleted() != BasicDoc.NOT_DELETE) {
            msg.fail("操作失败，船舶调配未找到");
            return msg;
        }
        if (oldDeployDriver.getStatus() != 0 && oldDeployDriver.getStatus() != 1) {
            msg.fail("操作失败，船舶调配状态必须是待开始或装船中");
            return msg;
        }
        //--------------查询供应商调配信息--------------
        //查港口
        SupplierPort supplierPort= supplierPortMapper.selectById(oldDeployDriver.getStartPortId());
        for (VehicleDeployCarCv deployCarTr : operationDdeploy.getCarList()) {
            if (!StringUtils.isNotBlank(deployCarTr.getBatchNumber())) {
                msg.fail("装船失败，运输计划委托车批次号不能为空");
                return msg;
            }
            if (!StringUtils.isNotBlank(deployCarTr.getWaybillNo())) {
                msg.fail("装船失败，运输计划委托车运单号不能为空");
                return msg;
            }
            if (!StringUtils.isNotBlank(deployCarTr.getFrameNumber())) {
                msg.fail("装船失败，运输计划委托车车架号不能为空");
                return msg;
            }
            //--------------查询运输计划委托车--------------
//            TransportChildCv transportChild = transportChildMapper.selectById(deployCarTr.getId());
            TransportChildCv transportChild = transportChildMapper.selectOne(new QueryWrapper<TransportChildCv>()
                    .eq("batch_number",deployCarTr.getBatchNumber()).eq("waybill_no",deployCarTr.getWaybillNo())
                    .eq("frame_number",deployCarTr.getFrameNumber()).eq("is_deleted",0));
            if (transportChild == null || transportChild.getIsDeleted() != BasicDoc.NOT_DELETE) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                msg.fail("装车失败，运输计划委托车未找到");
                return msg;
            }
            if (!StringUtils.isNotBlank(transportChild.getActualPortId()) || !transportChild.getActualPortId().equals(supplierPort.getId())) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                StringBuffer buffer = new StringBuffer();

                msg.fail("委托车车架号未在当前港口");
                return msg;
            }
            DateFormat ft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date;
            try {
                date = ft.parse(operationDdeploy.getStartTime());
            } catch (Exception e) {
                date = null;
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                msg.fail("装车时间异常");
                return msg;
            }
            if (transportChild.getState() == 0) {
                ShipDeployInfo deployFleet=oldDeployDriver;
                //新增调配委托车
                VehicleDeployCarCv deployCar = new VehicleDeployCarCv();
                deployCar.setId(RandomHelper.uuid());
                deployCar.setPlayId(transportChild.getBasicId());
                deployCar.setCarId(transportChild.getId());
                deployCar.setType(1);
                deployCar.setBasicId(deployFleet.getId());
                deployCar.setBatchNumber(transportChild.getBatchNumber());      //批次号
                deployCar.setWaybillNo(transportChild.getWaybillNo());          //运单编号
                deployCar.setFrameNumber(transportChild.getFrameNumber());      //车架号
                deployCar.setBrandId(transportChild.getBrandId());
                deployCar.setBrand(transportChild.getBrandName());
                deployCar.setModelId(transportChild.getModelId());
                deployCar.setModel(transportChild.getModelName());
                deployCar.setConfig(transportChild.getConfig());
                deployCar.setColor(transportChild.getColor());
                deployCar.setWeight(transportChild.getWeight());
                deployCar.setLwh(transportChild.getLwh());
                deployCar.setSupplierId(oldDeployDriver.getSupplierId());
                deployCar.setSupplierName(oldDeployDriver.getSupplierName());
                deployCar.setPersonnelId(oldDeployDriver.getShipId());
                deployCar.setPersonnelName(oldDeployDriver.getShipName());
                //----------装车位置----------
                deployCar.setStartType(1);       //起始类型 0：区域 1：港口
                deployCar.setStartId(oldDeployDriver.getStartId());           //起始地id
                deployCar.setStartFullId(oldDeployDriver.getStartFullId());   //起始地id(包含父级id)
                deployCar.setStartName(oldDeployDriver.getStartName());       //起始地区域名称
                deployCar.setStartCoordinate(oldDeployDriver.getStartCoordinate());
                deployCar.setStartPortId(oldDeployDriver.getStartPortId());       //起始港id
                deployCar.setStartPortName(oldDeployDriver.getStartPortName());   //起始港名
                //----------交车位置----------
                deployCar.setDeliveryType(1);       //交车类型 1：港口
                deployCar.setDeliveryId(oldDeployDriver.getDeliveryId());
                deployCar.setDeliveryFullId(oldDeployDriver.getDeliveryFullId());
                deployCar.setDeliveryName(oldDeployDriver.getDeliveryName());
                deployCar.setDeliveryCoordinate(oldDeployDriver.getDeliveryCoordinate());
                deployCar.setDeliveryPortId(oldDeployDriver.getDeliveryPortId());
                deployCar.setDeliveryPortName(oldDeployDriver.getDeliveryPortName());
                deployCar.setVoyageNumber(oldDeployDriver.getVoyageNumber());

                deployCar.setCreateTime(new Date());
                deployCar.setLoadingDate(date);
                deployCar.setState(1);
                carCvMapper.insert(deployCar);
            } else if (transportChild.getState() == 2) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                msg.fail("装车失败，委托车运输中");
                return msg;
            } else if (transportChild.getState() == 3) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                msg.fail("装车失败，委托车已交车");
                return msg;
            } else {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                msg.fail("装车失败，委托车信息待完善");
                return msg;
            }
            //-------------修改计划委托车信息-------------
            if (transportChild.getIsOutStorage() == 0 || transportChild.getLoadingDate() == null) {
                transportChild.setIsOutStorage(1);
                transportChild.setLoadingDate(date);
            }
            transportChild.setState(2);
        }
        //-------------修改供应商调配-------------
        oldDeployDriver.setLeftoverNum(oldDeployDriver.getLeftoverNum() + operationDdeploy.getCarList().size());
        oldDeployDriver.setStatus(1);
        shipDeployInfoMapper.updateById(oldDeployDriver);

        OperateRecord ope = new OperateRecord();
        ope.setId(RandomHelper.uuid());
        ope.setOperateType("添加装船");
        ope.setSourceId(operationDdeploy.getId());
        ope.setRemark(String.valueOf(operationDdeploy.getCarList().size()));
        if (empVo!=null){
            ope.setOperationName(empVo.getEmpNm());
            ope.setOperationId(empVo.getId());
        }
        operateRecordMapper.insert(ope);
        msg.success("手动装船成功");
        return msg;
    }

    @Override
    public ResponseMsg<Object> detail(String id) {
        ResponseMsg<Object> msg = new ResponseMsg<>();
        //查询供应商任务
        ShipDeployInfo deployFleet = shipDeployInfoMapper.selectById(id);
        if (deployFleet != null) {
            //查询卸车数量
//            List<VehicleDeployCarCv> carCvs = carCvMapper.deliveryPlace(deployFleet.getId());
            deployFleet.setCarList(carCvMapper.selectList(new QueryWrapper<VehicleDeployCarCv>().eq("basic_id", deployFleet.getId())
                    .eq("is_deleted", 0)));
            //查询操作记录
            List<OperateRecord> operateRecordList = operateRecordMapper.selectList(new QueryWrapper<OperateRecord>()
                    .eq("sourceId", deployFleet.getId())
                    .orderByDesc("create_time"));
            deployFleet.setOperateRecordList(operateRecordList);
        }
        msg.success("查询成功");
        msg.setData(deployFleet);
        return msg;
    }

    @Override
    @Transactional
    public ResponseMsg<Object> fulfilTransport(ShipDeployInfo newDeployDriver, EmployeeVo empVo) {
        ResponseMsg<Object> msg = new ResponseMsg<Object>();
        //验证司机调配是否存在
        ShipDeployInfo deployDriver = shipDeployInfoMapper.selectById(newDeployDriver.getId());
        if (deployDriver == null || deployDriver.getIsDeleted() != BasicDoc.NOT_DELETE) {
            msg.fail("操作失败，船舶调配未找到");
            return msg;
        }
        if (deployDriver.getStatus() != 1) {
            msg.fail("操作失败，船舶调配状态必须是执行中");
            return msg;
        }
        List<String> uodateCarCvList = new ArrayList<>();//批量更新调配委托车
        List<TransportChildCv> childCvs = new ArrayList<>();//更新计划委托车
        //查询调配委托车信息
        List<VehicleDeployCarCv> deployCarList = carCvMapper.selectList(new QueryWrapper<VehicleDeployCarCv>()
                .eq("basic_id", deployDriver.getId())
                .eq("state", 1)
                .eq("is_deleted", BasicDoc.NOT_DELETE));
        //批量查计划委托车
        List<TransportChildCv> transportChildCvs = transportChildMapper.batchTransportChildCvList(deployDriver.getId());//计划委托车
        List<TransportPlanCv> planCvList = planCvMapper.bctchQueryPlanList(deployDriver.getId());//计划
        ConcurrentMap<String, TransportChildCv> chlidCvMap = new ConcurrentHashMap<>();
        ConcurrentMap<String, TransportPlanCv> planCvMap = new ConcurrentHashMap<>();
        for (TransportChildCv c : transportChildCvs) {
            chlidCvMap.put(c.getId(), c);
        }
        for (TransportPlanCv p : planCvList) {
            planCvMap.put(p.getId(), p);
        }
        for (VehicleDeployCarCv deployCar : deployCarList) {
            TransportChildCv childCv = chlidCvMap.get(deployCar.getCarId());
            if (childCv == null) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                msg.fail("操作失败，计划中的委托车未找到");
                return msg;
            }
            if (childCv.getBasicId() == null) {
                msg.fail("操作失败，无计划车架号请先录入计划");
                return msg;
            }
            TransportPlanCv planCv = planCvMap.get(childCv.getBasicId());
            if (planCv == null) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                msg.fail("操作失败，计划不存在！");
                return msg;
            }
//            boolean judge = false;
            //赋值当前位置
            childCv.setActualPositionId(deployCar.getDeliveryId());
            childCv.setActualPositionFullId(deployCar.getDeliveryFullId());
            childCv.setActualPositionName(deployCar.getDeliveryName());
            childCv.setActualPositionCoordinate(deployCar.getDeliveryCoordinate());
//            if (deployDriver.getDeliveryType() == 1) { //港口交车
            childCv.setActualPortId(deployCar.getDeliveryPortId());
            childCv.setActualPortName(deployCar.getDeliveryPortName());
//                judge = true;
//            } else {
//                childCv.setActualPortId(null);
//                childCv.setActualPortName(null);
//            }
            DateFormat ft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date;
            try {
                date = ft.parse(newDeployDriver.getEndTime());
            } catch (Exception e) {
                date = null;
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                msg.fail("卸船时间异常");
                return msg;
            }
            //比较交车地是否一致，一致则计划委托车完成  针对 计划 到达地类型：1区域，2港口    调配  0：区域 1：港口
//            if ((deployCar.getDeliveryType() == 0 && deployCar.getDeliveryId().equals(childCv.getArrivePlaceId()) && childCv.getArrivePlaceType() == 1)
//                    || (deployCar.getDeliveryType() == 1 && deployCar.getDeliveryPortId().equals(childCv.getArrivePortId()) && childCv.getArrivePlaceType() == 2)) {
//                childCv.setState(3);
//                if (newDeployDriver.getEndTime() != null) {
//                    childCv.setDeliveryDate(date);
//                } else {
//                    childCv.setDeliveryDate(new Date());
//                }
//            } else {
//                childCv.setState(0);
//            }
            SupplierPort supplierPort = supplierPortMapper.selectOne(new QueryWrapper<SupplierPort>().eq("port_name",deployDriver.getDeliveryPortName()));
            if (childCv.getArrivePlaceType() == 2 && childCv.getArrivePortId().equals(supplierPort.getId())) {
                childCv.setDeliveryDate(new Date());
                childCv.setState(3);
            } else {
                childCv.setState(0);
            }
            childCvs.add(childCv);
            uodateCarCvList.add(deployCar.getId());
        }
        //批量更新委托车
        if (uodateCarCvList.size() > 0) {
            carCvMapper.batchUpdateDeployCarCv(uodateCarCvList, deployDriver.getEndTime());
        }
        //更新计划委托车
        if (childCvs.size() > 0) {
            transportChildMapper.batchUpdatePlanCurrentLocation2(childCvs);
        }

        ShipDeployInfo fleetCv = new ShipDeployInfo();
        fleetCv.setStatus(2);
        fleetCv.setUnloadedNumber(deployDriver.getUnloadedNumber() +uodateCarCvList.size());
        shipDeployInfoMapper.update(fleetCv, new QueryWrapper<ShipDeployInfo>().eq("id", newDeployDriver.getId()));
        WaterwaySupplierShip highwaySupplierCar = new WaterwaySupplierShip();
        highwaySupplierCar.setStatus(0);
        waterSupplierShipMapper.update(highwaySupplierCar, new QueryWrapper<WaterwaySupplierShip>().eq("id", deployDriver.getShipId()));
        //添加操作记录
        OperateRecord ope = new OperateRecord();
        ope.setId(RandomHelper.uuid());
        ope.setOperateType("卸船完成");
        ope.setSourceId(deployDriver.getId());
        if (empVo != null) {
            ope.setOperationName(empVo.getEmpNm());
            ope.setOperationId(empVo.getId());
        }
        operateRecordMapper.insert(ope);
        msg.success("操作成功");
        return msg;

    }
}

